#include "CSession.h"
#include "CServer.h"
#include "boost/uuid/uuid.hpp"
#include "boost/uuid/uuid_generators.hpp"
#include "boost/uuid/uuid_io.hpp"
#include <iostream>
#include "LogicSystem.h"
#include "LogicNode.h"


CSession::CSession(boost::asio::io_context& io_context,CServer* server)
:_socket(io_context),_server(server),
_b_head_parse(false)
{
    _recv_head_node = std::make_shared<MsgNode>(HEAD_TOTAL_LEN);
    //使用boost库生成uuid
    boost::uuids::uuid  a_sessionid = boost::uuids::random_generator()();
	_session_id = boost::uuids::to_string(a_sessionid);
}


CSession::~CSession()
{
    Close();
}

tcp::socket& CSession::GetSocket()
{
    return _socket;
}



void CSession::Start()
{
    AsyncReadHead(HEAD_TOTAL_LEN);
}


void CSession::Send(std::string msg, short msgid)
{
    Send(msg.c_str(),msg.size(),msgid);
}

void CSession::Send(const char* msg,  short max_length, short msgid)
{
    std::lock_guard<std::mutex> lock(_send_lock);
    int send_que_size = _send_msg_queue.size();
    if (send_que_size>MAX_SENDQUE)
    {
        std::cout<<"CSession::Send() send_que_size has exceed max size"<<std::endl;
        return;
    }
    std::shared_ptr<SendMsgNode> sendNode = std::make_shared<SendMsgNode>(msg,max_length,msgid);
    _send_msg_queue.push(sendNode);

    //此时判断send_que_size是否为0，如果为0，这异步的将消息发送出去，否则直接返回
    if(send_que_size!=0) return;
    std::cout<<"发送的消息 = "<<msg<<'\n';
    //异步的将信息发送出去
    boost::asio::async_write(_socket,boost::asio::buffer(sendNode->_data,sendNode->_total_len),
                                                            std::bind(&CSession::HandlerWrite,this,
                                                                    std::placeholders::_1,SharedSelf()));
}



std::shared_ptr<CSession> CSession::SharedSelf()
{
    return shared_from_this();
}


//此函数的意思是异步读取maxLength字节数据，调用handler处理
void CSession::AsyncReadFull(std::size_t maxLength,
        std::function<void (const boost::system::error_code& , std::size_t)> handler)
{
    memset(_data,0x00,MAX_LENGTH);
    AsyncReadLen(0,maxLength,handler);
}
void CSession::AsyncReadLen(std::size_t read_len, std::size_t total_len,
    std::function<void(const boost::system::error_code&, std::size_t)> handler)
{
    auto self(SharedSelf());
    _socket.async_read_some(boost::asio::buffer(_data+read_len,total_len-read_len),
                            [self,handler,read_len,total_len](const boost::system::error_code& ec , std::size_t bytes_transferred){
        if (ec)
        {
            std::cout<<"AsyncReadLen error:"<<ec.message()<<std::endl;
            self->Close();
            self->_server->ClearSession(self->_session_id);
            return;
        }
        //如果读取的字节数小于总长度，说明还没读完数据，还需要继续读取
        if(read_len+bytes_transferred<total_len)
        {
            self->AsyncReadLen(read_len+bytes_transferred,total_len,handler);
            return;
        }

        //如果读取完成，调用handler处理
        handler(ec,read_len+bytes_transferred);
                                    
    });
}



void CSession::AsyncReadHead(int total_len)
{
    auto self(SharedSelf());
    AsyncReadFull(HEAD_TOTAL_LEN,[self](const boost::system::error_code& ec , std::size_t total_transferred){
        if(ec)
        {
            std::cout<<"AsyncReadHead error:"<<ec.message()<<std::endl;
            self->Close();
            self->_server->ClearSession(self->_session_id);
            return;
        }
        

        self->_recv_head_node->Clear();
        //代码走到此处表示已经读完头部数据，所以接下来准备解析头部数据
        short msgid=0;
        memcpy(&msgid,self->_data,HEAD_ID_LEN);

        short data_len=0;
        memcpy(&data_len,self->_data+HEAD_ID_LEN,HEAD_DATA_LEN);

        //进行字节序转换
         msgid = boost::asio::detail::socket_ops::network_to_host_short(msgid);
        data_len = boost::asio::detail::socket_ops::network_to_host_short(data_len);
        if(msgid>MAX_LENGTH)
        {
            std::cout<<"AsyncReadHead error:msgid>MAX_LENGTH"<<std::endl;
            self->Close();
            self->_server->ClearSession(self->_session_id);
            return;
        }
        if(data_len>MAX_LENGTH)
        {
            std::cout<<"AsyncReadHead error:data_len>MAX_LENGTH"<<std::endl;
            self->Close();
            self->_server->ClearSession(self->_session_id);
            return;
        }

        //构建消息节点
        self->_recv_msg_node = std::make_shared<RecvMsgNode>(data_len,msgid);
        //异步的读取消息体数据
        self->AsyncReadBody(data_len);


    });
}



void CSession::AsyncReadBody(int length)
{
    //TODO:基于length异步读取消息体数据
    auto self(SharedSelf());
    AsyncReadFull(length,[self](const boost::system::error_code& ec , std::size_t total_transferred){

        if(ec)
        {
            std::cout<<"AsyncReadBody error:"<<ec.message()<<std::endl;
            self->Close();
            self->_server->ClearSession(self->_session_id);
            return;
        }

        //将数据从缓存中复制到消息节点
        memcpy(self->_recv_msg_node->_data,self->_data,total_transferred);
        self->_recv_msg_node->_cur_len = total_transferred;
        
        //输出接收的信息
        std::cout<<"AsyncReadBody success:msgid="<<self->_recv_msg_node->_msg_id<<
                                                ",data_len="<< self->_recv_msg_node->_cur_len<< \
                                                       ",data="<<self->_recv_msg_node->_data<<std::endl;
        
        //TODO 将消息放入逻辑系统进行处理，逻辑系统处理完毕后利用异步发送，将消息发送出去
        std::shared_ptr<LogicNode> logic_node = std::make_shared<LogicNode>(self,self->_recv_msg_node);
        LogicSystem::GetInstance()->PostLogicNodeToQueue(logic_node);

        //继续监听头部数据
        self->AsyncReadHead(HEAD_TOTAL_LEN);
    });
}




void CSession::HandlerWrite(const boost::system::error_code& error,
                                     std::shared_ptr<CSession> shared_self)
{
    try
    {
        
        if (error)
        {
            std::cerr<<"HandlerWrite error:"<<error.message()<<" error value:"<<error.value()<<std::endl;
            shared_self->Close();
            shared_self->_server->ClearSession(shared_self->_session_id);
            return;
        }
        
        
        
        std::lock_guard<std::mutex> lock(_send_lock);
        _send_msg_queue.pop();
        //判断发送队列是否为空，不为空则继续注册异步发送
        if(_send_msg_queue.size()==0)
        {
            return;
        }
        auto sendNode = _send_msg_queue.front();
        boost::asio::async_write(_socket,boost::asio::buffer(sendNode->_data,sendNode->_total_len),
                                                                std::bind(&CSession::HandlerWrite,this,
                                                                        std::placeholders::_1,shared_self));
        


    }
    catch(const std::exception& e)
    {
        std::cerr <<"HandlerWrite error:"<< e.what() << '\n';
        return;
    }
    
        


        
}

void CSession::Close()
{
    _socket.close();
    _b_close = true;
}


std::string& CSession::GetSessionId()
{
    return _session_id;
}

// 绑定用户的uid
void CSession::SetUserId(int uid)
{
    _user_uid = uid;
}

// 获取用户的uid
int CSession::GetUserId()
{
    return _user_uid;
}